home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Telnet 2.7b5 / source / debug⁄errors / DlogUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-24  |  19.1 KB  |  730 lines  |  [TEXT/CWIE]

  1. /*
  2. *    DlogUtils.c
  3. *    Very Useful Dialog Utilities Apple SHOULD have provided in the toolbox...
  4. *
  5. *****************************************************************
  6. *    NCSA Telnet for the Macintosh                                *
  7. *                                                                *
  8. *    National Center for Supercomputing Applications                *
  9. *    Software Development Group                                    *
  10. *    152 Computing Applications Building                            *
  11. *    605 E. Springfield Ave.                                        *
  12. *    Champaign, IL  61820                                        *
  13. *                                                                *
  14. *    Copyright (c) 1986-1992,                                    *
  15. *    Board of Trustees of the University of Illinois                *
  16. *****************************************************************
  17. *  Revisions:
  18. *  8/92        Telnet 2.6:    Initial version.  Jim Browne
  19. */
  20.  
  21. #ifdef MPW
  22. #pragma segment Debug
  23. #endif
  24.  
  25. #include "DlogUtils.proto.h"
  26. #include "netevent.proto.h"
  27.  
  28. #include "Popup.h"
  29. #include "popup.proto.h"
  30.  
  31. pascal short modalProc(DialogPtr dptr, EventRecord *evt, short *item);
  32. PROTO_UPP(modalProc, ModalFilter);
  33. pascal short FileHook(short item, DialogPtr theDialog);
  34. PROTO_UPP(FileHook, DlgHook);
  35. pascal Boolean    FolderFilter(FileParam *pbp);
  36. PROTO_UPP(FolderFilter, FileFilter);
  37.  
  38. void GetTEText( DialogPtr dptr, short item, Str255 str)
  39. {
  40.     short type;
  41.     Handle itemh;
  42.     Rect theRect;
  43.  
  44.     GetDItem(dptr, item, &type, &itemh, &theRect);
  45.     GetIText(itemh, str);
  46. }
  47.  
  48. void SetTEText( DialogPtr dptr, short item, Str255 str)
  49. {
  50.     short type;
  51.     Handle itemh;
  52.     Rect theRect;
  53.  
  54.     GetDItem(dptr, item, &type, &itemh, &theRect);
  55.     SetIText(itemh, str);
  56. }
  57.  
  58. void Hilite( DialogPtr dptr, short item, short value)
  59. {
  60.     short Type;
  61.     Handle Itemh;
  62.     Rect Box;
  63.  
  64.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  65.     HiliteControl((ControlHandle)Itemh, value);
  66. }
  67.  
  68. void FlipCheckBox( DialogPtr dptr, short item)
  69. {
  70.     short type;
  71.     Handle itemHdl;
  72.     Rect box;
  73.  
  74.     GetDItem(dptr, item, &type, &itemHdl, &box);
  75.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  76. }
  77.  
  78. void FlipRadioButton( DialogPtr dptr, short item)
  79. {
  80.     short type;
  81.     Handle itemHdl;
  82.     Rect box;
  83.  
  84.     GetDItem(dptr, item, &type, &itemHdl, &box);
  85.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  86. }
  87.  
  88. void SetCntrl( DialogPtr dptr, short item, short value)
  89. {
  90.     short Type;
  91.     Handle Itemh;
  92.     Rect Box;
  93.  
  94.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  95.     SetCtlValue((ControlHandle)Itemh, value);
  96. }
  97.  
  98. short GetCntlVal( DialogPtr dptr, short item)
  99. {
  100.     short Type;
  101.     Handle Itemh;
  102.     Rect Box;
  103.  
  104.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  105.     return GetCtlValue((ControlHandle)Itemh);
  106. }
  107.  
  108. short findPopupMenuItem(MenuHandle theHandle, Str255 name)
  109. {
  110.     short id;
  111.     Str255     tempName;
  112.     short numItems;
  113.  
  114.     numItems = CountMItems(theHandle);
  115.     for (id = 1; id < numItems; id++)
  116.     {
  117.         GetItem(theHandle,id,tempName);
  118.         if (EqualString(tempName, name, 0, 0))
  119.             break;
  120.     }
  121.  
  122.     return id;
  123. }
  124.  
  125. #ifndef NO_UNIVERSAL
  126. void UItemAssign( DialogPtr dptr, short item, UserItemUPP proc)
  127. #else
  128. void UItemAssign( DialogPtr dptr, short item, ProcPtr proc)
  129. #endif
  130. /* sets the handler for a user item to the specified procedure. */
  131. {
  132.     Rect ibox;
  133.     char **ihndl;
  134.     short typ;
  135.  
  136.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  137.     SetDItem( dptr, item,  typ, (Handle) proc, &ibox);
  138. }
  139.  
  140. SIMPLE_UPP(OutlineItem, UserItem);
  141. pascal void OutlineItem( DialogPtr dptr, short itm)
  142. {
  143.     Rect ibox;
  144.     char **ihndl;
  145.     short typ;
  146.     short item=itm;
  147.     
  148.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  149.     PenSize( 3,3);
  150.     InsetRect( &ibox, -4,-4);
  151.     FrameRoundRect( &ibox, 16,16);
  152. }
  153.  
  154. SIMPLE_UPP(VersionNumber, UserItem);
  155. pascal void VersionNumber( DialogPtr dptr, short itm)
  156. {
  157.     Rect ibox;
  158.     char **ihndl;
  159.     short typ;
  160.     short item=itm;
  161.     VersRecHndl version;
  162.     Str63 versionString;
  163.  
  164.     if ((version = (VersRecHndl) GetResource('vers',1)) != nil)
  165.     {
  166.         BlockMove((*version)->shortVersion+*(*version)->shortVersion+1, versionString, *((*version)->shortVersion+*(*version)->shortVersion+1)+1);
  167.         ReleaseResource((Handle)version);
  168.     }
  169.     else
  170.         *versionString = 0;
  171.  
  172.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  173.     TextFont( 3);
  174.     TextSize( 9);
  175.     MoveTo( ibox.left+((ibox.right-ibox.left)/2)-(StringWidth(versionString)/2), ibox.bottom-2);
  176.     DrawString(versionString);
  177. }
  178.  
  179. SIMPLE_UPP(modalProc, ModalFilter);
  180. pascal short modalProc( DialogPtr dptr, EventRecord *evt, short *item)
  181. {
  182.     UNUSED_ARG(dptr)
  183.     short keyCode, key;
  184.  
  185.     if (evt->what == keyDown) {
  186.         key = evt->message & charCodeMask;
  187.         keyCode = (evt->message >>8) & 0xff ;
  188.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  189.             *item = DLOGOk;
  190.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  191.             }
  192.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  193.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  194.             *item = DLOGCancel;
  195.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  196.             }
  197.         }
  198.     Stask();
  199.     return(FALSE);
  200. }
  201.  
  202. void FlashButton (DialogPtr theDialog, short item)
  203. {
  204.     short itemType;
  205.     ControlHandle theItem;
  206.     Rect itemRect;
  207.     long myticks;
  208.     
  209.     if (item > 0) {
  210.         GetDItem(theDialog,item,&itemType,(Handle *)&theItem,&itemRect);
  211.         HiliteControl(theItem,1);
  212.         Delay(8,&myticks);
  213.         HiliteControl(theItem,0);
  214.     }
  215. }
  216.  
  217. SIMPLE_UPP(DLOGwOK, ModalFilter);
  218. pascal short DLOGwOK( DialogPtr dptr, EventRecord *evt, short *item)
  219. {
  220.     return(MyDLOGfilter(dptr, evt, item, true, false, false));
  221. }
  222.  
  223. SIMPLE_UPP(DLOGwOK_Cancel, ModalFilter);
  224. pascal short DLOGwOK_Cancel( DialogPtr dptr, EventRecord *evt, short *item)
  225. {
  226.     return(MyDLOGfilter(dptr, evt, item, true, true, false));
  227. }
  228.  
  229. SIMPLE_UPP(DLOGwOK_Cancel_Popup, ModalFilter);
  230. pascal short DLOGwOK_Cancel_Popup( DialogPtr dptr, EventRecord *evt, short *item)
  231. {
  232.     return(MyDLOGfilter(dptr, evt, item, true, true, true));
  233. }
  234.  
  235. //    Our standard modal dialog box filter.
  236. SIMPLE_UPP(MyDLOGfilter, ModalFilter);
  237. pascal short MyDLOGfilter( DialogPtr dptr, EventRecord *evt, short *item, 
  238.                             Boolean hasOK, Boolean hasCancel, Boolean hasPopup)
  239. {
  240.     short keyCode, key, iType;
  241.     Handle iHndl;
  242.     Rect iRect;
  243.  
  244.     SetPort(dptr);
  245.     if (evt->what == keyDown) {
  246.         key = evt->message & charCodeMask;
  247.         keyCode = (evt->message >>8) & 0xff ;
  248.         if (((key == 0x0d) || (key == 0x03)) && hasOK) { // 0x0d == return, 0x03 == enter
  249.             *item = DLOGOk;                // ok
  250.             FlashButton(dptr, DLOGOk);
  251.             return(-1);
  252.             }
  253.         if ((((key == '.') && (evt->modifiers & cmdKey)) ||
  254.             ((key == 0x1b) && (keyCode == 0x35))) && hasCancel) {    // 0x35 == escKey
  255.             *item = DLOGCancel;
  256.             FlashButton(dptr, DLOGCancel);
  257.             return(-1);
  258.             }
  259.         }
  260.     else if ((evt->what == updateEvt) && hasOK) {
  261.         if ((WindowPtr)evt->message == dptr) {
  262.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  263.             PenSize(3,3);
  264.             InsetRect(&iRect,-4,-4);
  265.             FrameRoundRect(&iRect,16,16);
  266.             }
  267.     }
  268.     
  269.     if ((evt->what == mouseDown) && hasPopup)
  270.         return(PopupMousedown(dptr, evt, item));
  271.  
  272.     Stask();
  273.     return(FALSE);
  274. }
  275.  
  276. #if 0
  277. //    Our standard modal dialog box filter with code to handle popup user items.
  278. pascal short MyDLOGfilterWPopupFilter( DialogPtr dptr, EventRecord *evt, short *item)
  279. {
  280.     short keyCode, key, iType;
  281.     Handle iHndl;
  282.     Rect iRect;
  283.  
  284.     SetPort(dptr);
  285.     if (evt->what == keyDown) {
  286.         key = evt->message & charCodeMask;
  287.         keyCode = (evt->message >>8) & 0xff ;
  288.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  289.             *item = DLOGOk;                // ok
  290.             FlashButton(dptr, DLOGOk);
  291.             return(-1);
  292.             }
  293.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  294.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  295.             *item = DLOGCancel;
  296.             FlashButton(dptr, DLOGCancel);
  297.             return(-1);
  298.             }
  299.         }
  300.     else if (evt->what == updateEvt) {
  301.         if ((WindowPtr)evt->message == dptr) {
  302.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  303.             PenSize(3,3);
  304.             InsetRect(&iRect,-4,-4);
  305.             FrameRoundRect(&iRect,16,16);
  306.             }
  307.     }
  308.     
  309.     if (evt->what == mouseDown) return(PopupMousedown(dptr, evt, item));
  310.     Stask();
  311.     return(FALSE);
  312. }
  313. #endif
  314.  
  315. #ifdef    NO_UNIVERSAL
  316. #define LMSetSFSaveDisk(SFSaveDiskValue) ((* (short *) 0x0214) = (SFSaveDiskValue))
  317. #define LMGetSFSaveDisk() (* (short *) 0x0214)
  318. #define LMGetCurDirStore() (* (long *) 0x0398)
  319. #define LMSetCurDirStore(CurDirStoreValue) ((* (long *) 0x0398) = (CurDirStoreValue))
  320. #endif
  321.  
  322. void    SelectDirectory(short *VRefNum, long *DirID)
  323. {
  324.     Point        where;
  325.     SFReply        sfr;
  326.     
  327.     LMSetSFSaveDisk( - (*VRefNum));
  328.     LMSetCurDirStore(*DirID);
  329.     
  330.     StandardFileCenter(&where, WDSET_DLOG);
  331.     
  332.     TelInfo->setdir = 0;                    /* clear dir found flag */
  333.     
  334.     SFPGetFile( where, NULL, FolderFilterUPP, -1, NULL,    /* BYU LSC */
  335.         FileHookUPP, &sfr, WDSET_DLOG,
  336.         modalProcUPP); 
  337.  
  338.     if (TelInfo->setdir)                    /* we got a dir */
  339.     {
  340.         *VRefNum = - LMGetSFSaveDisk();
  341.         *DirID = LMGetCurDirStore();
  342.     }    
  343. }
  344.  
  345. SIMPLE_UPP(FileHook, DlgHook);
  346. pascal short    FileHook( short item, DialogPtr theDialog)
  347. {
  348. #ifdef    MPW
  349. #pragma unused(theDialog)
  350. #endif
  351.     if(item == 11) {                    /* Set Directory Button */
  352.             TelInfo->setdir = 1;
  353.             
  354.             return(3);        /* pretend we hit cancel, but we didn't */
  355.         }
  356.     else if (item == 12)
  357.         item = 9;            /* these don't count, map to disabled item */
  358.  
  359.     return(item);
  360. }
  361.  
  362. SIMPLE_UPP(FolderFilter, FileFilter);
  363. pascal Boolean    FolderFilter(FileParam *pbp)
  364. {
  365.     if (pbp->ioFlAttrib & 0x0010) return(FALSE);
  366.     else return(-1);
  367. }
  368.  
  369. OSErr SetIndString(StringPtr theStr,short resID,short strIndex)
  370. {
  371.        Handle theRes;               /* handle pointing to STR# resource */
  372.        short numStrings;            /* number of strings in STR# */
  373.        short ourString;             /* counter to index up to strIndex */
  374.        char *resStr;                /* string pointer to STR# string to replace */
  375.        long oldSize;                /* size of STR# resource before call */
  376.        long newSize;                /* size of STR# resource after call */
  377.     unsigned long offset;        /* resource offset to str to replace*/
  378.     OSErr memError;
  379.    /* make sure index is in bounds */
  380.  
  381.    if (resID < 1)
  382.    return -1;
  383.  
  384.    /* make sure resource exists */
  385.  
  386.    theRes = GetResource('STR#',resID);
  387.    if (ResError()!=noErr)
  388.    return ResError();
  389.    if (!theRes || !(*theRes))
  390.    return resNotFound;
  391.  
  392.    HLock(theRes);
  393.    HNoPurge(theRes);
  394.  
  395.    /* get # of strings in STR# */
  396.  
  397.    BlockMove(*theRes,&numStrings,sizeof(short));
  398.    if (strIndex > numStrings)
  399.    return resNotFound;
  400.  
  401.    /* get a pointer to the string to replace */
  402.  
  403.    offset = sizeof(short);
  404.    resStr = (char *) *theRes + sizeof(short);
  405.    for (ourString=1; ourString<strIndex; ourString++) {
  406.    offset += 1+resStr[0];
  407.    resStr += 1+resStr[0];
  408.    }
  409.  
  410.    /* grow/shrink resource handle to make room for new string */
  411.  
  412.    oldSize = GetHandleSize(theRes);
  413.    newSize = oldSize - resStr[0] + theStr[0];
  414.    HUnlock(theRes);
  415.    memError = mySetHandleSize(theRes,newSize);
  416.    if (memError!=noErr) {
  417.    ReleaseResource(theRes);
  418.    return -1;
  419.    }
  420.    HLock(theRes);
  421.    resStr = *theRes + offset;
  422.  
  423.    /* move old data forward/backward to make room */
  424.  
  425.    BlockMove(resStr+resStr[0]+1, resStr+theStr[0]+1, oldSize-offset-resStr[0]-1);
  426.  
  427.    /* move new data in */
  428.  
  429.    BlockMove(theStr,resStr,theStr[0]+1);
  430.  
  431.    /* write resource out */
  432.  
  433.    ChangedResource(theRes);
  434.    WriteResource(theRes);
  435.    HPurge(theRes);
  436.    ReleaseResource(theRes);
  437.  
  438.    return ResError();
  439. }
  440.  
  441. /* A very special thanks to Steve Dorner (sdorner@qualcomm.com) for the following code! */
  442.  
  443. /************************************************************************
  444.  * GetNewMyDialog - get a new dialog, with a bit extra
  445.  ************************************************************************/
  446. WindowPtr GetNewMyDialog(short template,Ptr wStorage,WindowPtr behind,
  447.     void (*centerFunction)(short))
  448. {
  449.     WindowPtr win;
  450.     
  451.     if (wStorage == nil)
  452.     {
  453.         if ((wStorage=myNewPtrCritical(sizeof(DialogRecord)))==nil)
  454.             return (nil);
  455.     }
  456.     WriteZero(wStorage, sizeof(WindowRecord));
  457.     
  458.     (*centerFunction)(template);
  459.     win = GetNewDialog(template, wStorage, behind);
  460.     if (win==nil) return(nil);
  461.     SetPort(win);
  462. /*    win->contR = ((GrafPtr)win)->portRect; */
  463. /*    win->qWindow.refCon = CREATOR; */
  464.     return(win);
  465. }
  466.  
  467. /* Do a GetNewMyDialog, but make the text small... */
  468. WindowPtr GetNewMySmallDialog(short template,Ptr wStorage,WindowPtr behind,
  469.     void (*centerFunction)(short))
  470. {
  471.     short size;
  472.     DialogPtr dlogptr;
  473.     
  474.     size = 9;
  475.     SetDAFont(applFont);
  476.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  477.     SetDAFont(systemFont);
  478.     if (dlogptr==nil)
  479.         return 0;
  480.     SetPort(dlogptr);
  481.     TextSize(size);
  482.     TextFont(applFont);
  483.     {
  484.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  485.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  486.         (*teh)->txSize = size;
  487.         (*teh)->lineHeight = GetLeading(applFont,size);
  488.         (*teh)->fontAscent = GetAscent(applFont,size);
  489.     }            
  490.  
  491.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  492.         and then do a ShowWindow.  This keeps the Control Manager from every using Chicago
  493.         on our turf. -- JMB */
  494.         
  495.     if (! ((((DialogPeek) dlogptr)->window).visible)) ShowWindow(dlogptr);
  496.     
  497.     return(dlogptr);
  498. }
  499.  
  500. /* Do a GetNewMySmallDialog, but read the item titles from a STR#... */
  501. WindowPtr GetNewMySmallStrangeDialog(short template,Ptr wStorage,WindowPtr behind,
  502.     void (*centerFunction)(short))
  503. {
  504.     short         size, index, limit, itemType;
  505.     DialogPtr     dlogptr;
  506.     Handle        resource;
  507.     ControlHandle    itemHandle;
  508.     Rect        scratchRect;
  509.     Str255        scratchPstring;
  510.     
  511.     size = 9;
  512.     SetDAFont(applFont);
  513.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  514.     SetDAFont(systemFont);
  515.     if (dlogptr==nil)
  516.         return 0;
  517.     SetPort(dlogptr);
  518.     TextSize(size);
  519.     TextFont(applFont);
  520.     {
  521.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  522.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  523.         (*teh)->txSize = size;
  524.         (*teh)->lineHeight = GetLeading(applFont,size);
  525.         (*teh)->fontAscent = GetAscent(applFont,size);
  526.     }            
  527.  
  528.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  529.         and then do a ShowWindow.  This keeps the Control Manager from ever using Chicago
  530.         on our turf. -- JMB */
  531.     
  532.     if ((resource = GetResource('STR#', template)) != NULL) {
  533.         short base;
  534.         Str255 baseStr;
  535.         
  536.         GetIndString(baseStr, template, 1);
  537.         base = atoi(p2cstr(baseStr));
  538.         
  539.         limit = *(short *)(*resource);
  540.         ReleaseResource(resource);
  541.         
  542.         for(index = 2; index <= limit; index++) {
  543.             GetDItem(dlogptr, index + base, &itemType, (Handle *)&itemHandle, &scratchRect);
  544.             if ((itemType == 7) && ((**itemHandle).contrlRfCon == 1991)) {
  545.                 GetIndString(scratchPstring, template, index);
  546.                 SetCTitle(itemHandle, scratchPstring);
  547.                 }
  548.             }
  549.         }
  550.                 
  551.     return(dlogptr);
  552. }
  553.  
  554. /**********************************************************************
  555.  * write zeroes over an area of memory
  556.  **********************************************************************/
  557. void WriteZero(Ptr pointer,long size)
  558. {
  559.     while (size--) *pointer++ = 0;
  560. }
  561.  
  562. /**********************************************************************
  563.  * figure out the appropriate leading for a font
  564.  **********************************************************************/
  565. short GetLeading(short fontID,short fontSize)
  566. {
  567.     FMInput fInInfo;
  568.     FMOutput *fOutInfo;
  569.     
  570.     /* set up the font input struct */
  571.     fInInfo.family = fontID;
  572.     fInInfo.size = fontSize;
  573.     fInInfo.face = 0;
  574.     fInInfo.needBits = FALSE;
  575.     fInInfo.device = 0;
  576.     fInInfo.numer.h = fInInfo.numer.v = 1;
  577.     fInInfo.denom.h = fInInfo.denom.v = 1;
  578.     
  579.     /* get the actual info */
  580.     fOutInfo = FMSwapFont(&fInInfo);
  581.     
  582.     return(((fOutInfo->leading + fOutInfo->ascent + fOutInfo->descent)*fOutInfo->numer.v)/fOutInfo->denom.v);
  583. }
  584.  
  585. /**********************************************************************
  586.  * find ascent font
  587.  **********************************************************************/
  588. short GetAscent(short fontID,short fontSize)
  589. {
  590.     FMInput fInInfo;
  591.     FMOutput *fOutInfo;
  592.     
  593.     /*    set up the font input struct */
  594.     fInInfo.family = fontID;
  595.     fInInfo.size = fontSize;
  596.     fInInfo.face = 0;
  597.     fInInfo.needBits = FALSE;
  598.     fInInfo.device = 0;
  599.     fInInfo.numer.h = fInInfo.numer.v = 1;
  600.     fInInfo.denom.h = fInInfo.denom.v = 1;
  601.     
  602.     /*    get the actual info */
  603.     fOutInfo = FMSwapFont(&fInInfo);
  604.     
  605.     return((fOutInfo->ascent * fOutInfo->numer.v)/fOutInfo->denom.v);
  606. }
  607.  
  608. /************************************************************************
  609.  * CenterRectIn - center one rect in another
  610.  ************************************************************************/
  611. void CenterRectIn(Rect *inner,Rect *outer)
  612. {
  613.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  614.                                      (outer->top+outer->bottom-inner->top-inner->bottom)/2);                                                                    
  615. }
  616.  
  617. /************************************************************************
  618.  * TopCenterRectIn - center one rect in (the bottom of) another
  619.  ************************************************************************/
  620. void TopCenterRectIn(Rect *inner,Rect *outer)
  621. {
  622.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  623.                                      outer->top-inner->top);                                                                    
  624. }
  625.  
  626. /************************************************************************
  627.  * BottomCenterRectIn - center one rect in (the bottom of) another
  628.  ************************************************************************/
  629. void BottomCenterRectIn(Rect *inner,Rect *outer)
  630. {
  631.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  632.                                      outer->bottom-inner->bottom);                                                                    
  633. }
  634.  
  635. /************************************************************************
  636.  * ThirdCenterRectIn - center one rect in (the top 1/3 of) another
  637.  ************************************************************************/
  638. void ThirdCenterRectIn(Rect *inner,Rect *outer)
  639. {
  640.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  641.                                      outer->top-inner->top +
  642.                                      (outer->bottom-outer->top-inner->bottom+inner->top)/3);                                                                    
  643. }
  644.  
  645. void SecondThirdCenterRectIn(Rect *inner,Rect *outer)
  646. {
  647.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  648.                                      outer->top-inner->top +
  649.                                      2*(outer->bottom-outer->top-inner->bottom+inner->top)/3);                                                                    
  650. }
  651.  
  652. void ThirdCenterDialog(short id)
  653. {
  654.     DialogTHndl dTempl;
  655.     Rect r = qd.screenBits.bounds;
  656.     r.top += GetMBarHeight();       
  657.     
  658.     dTempl=(DialogTHndl)GetResource('ALRT',id);
  659.     if (!dTempl)
  660.            dTempl=(DialogTHndl)GetResource('DLOG',id);
  661.     if (dTempl)
  662.         ThirdCenterRectIn(&(*dTempl)->boundsRect,&r);
  663. }
  664. void SecondThirdCenterDialog(short id)
  665. {
  666.     DialogTHndl dTempl;
  667.     Rect r = qd.screenBits.bounds;
  668.     r.top += GetMBarHeight();       
  669.     
  670.     dTempl=(DialogTHndl)GetResource('ALRT',id);
  671.     if (!dTempl)
  672.            dTempl=(DialogTHndl)GetResource('DLOG',id);
  673.     if (dTempl)
  674.         SecondThirdCenterRectIn(&(*dTempl)->boundsRect,&r);
  675. }
  676.  
  677.  
  678. /************************************************************************
  679.  * StandardFileCenter - figure out where a stdfile dialog should go
  680.  ************************************************************************/
  681. void StandardFileCenter(Point *where, short id)
  682. {
  683.     Rect r,in;
  684.     DialogTHndl dTempl;             
  685.     dTempl=(DialogTHndl)GetResource('ALRT',id);
  686.     if (!dTempl)
  687.            dTempl=(DialogTHndl)GetResource('DLOG',id);
  688.     if (dTempl)
  689.     {
  690.         r = (*dTempl)->boundsRect;
  691.         in = qd.screenBits.bounds;
  692.         in.top += GetMBarHeight();
  693.         ThirdCenterRectIn(&r,&in);
  694.         where->h = r.left;
  695.         where->v = r.top;
  696.     }
  697.     else
  698.     {
  699.         where->h = 100;
  700.         where->v = 100;
  701.     }
  702. }
  703.  
  704. /* Pascal string utilities */
  705.  
  706. /*    pstrcat - add string 'src' to end of string 'dst' */
  707. void pstrcat(StringPtr dst, StringPtr src)
  708. {
  709.     /* copy string in */
  710.     BlockMove(src + 1, dst + *dst + 1, *src);
  711.     /* adjust length byte */
  712.     *dst += *src;
  713. }
  714.  
  715. /*    pstrinsert - insert string 'src' at beginning of string 'dst' */
  716. void pstrinsert(StringPtr dst, StringPtr src)
  717. {
  718.     /* make room for new string */
  719.     BlockMove(dst + 1, dst + *src + 1, *dst);
  720.     /* copy new string in */
  721.     BlockMove(src + 1, dst + 1, *src);
  722.     /* adjust length byte */
  723.     *dst += *src;
  724. }
  725.  
  726. void pstrcpy(StringPtr dst, StringPtr src)
  727. {
  728.     BlockMove(src, dst, *src + 1);
  729. }
  730.